﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MetaDrive.Core;
using MetaDrive.FluentCode;
using EnvDTE;
using EnvDTE80;

namespace MetaDrive.Library
{
    [SnippetInfo("Proxy")]
    public class ProxySnippet : Snippet
    {
        protected FluentCodeNamespace Namespace { get; set; }
        protected FluentCodeClass Class { get; set; }

        protected override void Visit(FluentCodeNamespace element)
        {
            Namespace = Target.Command.AddNamespace(element.Name);
        }

        protected override void Visit(FluentCodeClass element)
        {
            Class = Namespace.Command.AddClass(element.Name + "Proxy", element.Adaptee.Access, element.Name);
        }

        protected override bool PreVisit(FluentCodeProperty element)
        {
            return (element.Adaptee.Getter.CanOverride || element.Adaptee.Setter.CanOverride);
        }

        protected override void Visit(FluentCodeProperty element)
        {
            FluentCodeProperty codeProperty = Class.Command.AddProperty(element.Name, element.Adaptee.Type, element.Adaptee.Access);
            codeProperty.OverrideKind(vsCMOverrideKind.vsCMOverrideKindOverride);

            codeProperty.Getter.Edit.Body = string.Format("return base.{0};", codeProperty.Name);
            codeProperty.Setter.Edit.Body = string.Format("base.{0} = value;", codeProperty.Name);          
        }

        protected override bool PreVisit(FluentCodeFunction element)
        {
            return element.Adaptee.CanOverride;
        }

        protected override void Visit(FluentCodeFunction element)
        {            
            FluentCodeFunction codeFunction = Class.Command.InsertFunction(element);
            codeFunction.Adaptee.OverrideKind = vsCMOverrideKind.vsCMOverrideKindOverride;
                                    
            string pars = string.Join(",", codeFunction.Query.OfType<FluentCodeParameter>().Select(x => x.Name).ToArray());

            codeFunction.Edit.Body = string.Format("{0} base.{1}({2});", 
                (codeFunction.Adaptee.Type.TypeKind == vsCMTypeRef.vsCMTypeRefVoid) ? "" : "return",
                codeFunction.Name, 
                pars);                       
        }
    }
}
